/*
 * Ellipse.cpp
 *
 *      Author: Jerome RD Soine and Christoph A Brand
 *      Institution: Schwarz goup, Institute for Theoretical Physics, Heidelberg University, Germany
 */

#include "../../../include/core/shape/Ellipse.h"
#include <cmath>
#include <fstream>
#include <stdlib.h>
#include <iostream>
#include <sstream>
#include <cmath>


bool Ellipse::is_on_shape(vector<double> point)
{

	vector<double> translated_point (2,0);
	translated_point[0] = point[0]-center[0];
	translated_point[1] = point[1]-center[1];
	vector<double> rotated_pt = rotate(translated_point,-orientation_angle);
	double value = rotated_pt[0]*rotated_pt[0]/(a*a)
					+ rotated_pt[1]*rotated_pt[1]/(b*b);
	if(value<=1) return true;
	return false;
}

vector<double> Ellipse::rotate(vector<double> &point, double angle)
{
	vector<double> rotated_point (2);
	rotated_point[0] = point[0]*cos(angle) - point[1]*sin(angle);
	rotated_point[1] = point[0]*sin(angle) + point[1]*cos(angle);
	return rotated_point;
}

vector<Shape*> Ellipse::get_shapes_from_file(string filename)
{
	vector<double> x_pos;
	vector<double> y_pos;
	vector<double> angle;
	vector<double> major;
	vector<double> minor;

	ifstream input (filename.c_str());
	if(input.good())
	{
		string line;
		while(getline(input,line)){
			istringstream iline(line);
			string str_value;
			double d_value;
//			cout << "Ellipse: ";

			getline(iline, str_value, '\t');
			d_value = atof(str_value.c_str());
			x_pos.push_back(d_value);
//			cout << "x="<<d_value;

			getline(iline, str_value, '\t');
			d_value = atof(str_value.c_str());
			y_pos.push_back(d_value);
//			cout << " - y="<<d_value;

			getline(iline, str_value, '\t');
			d_value = atof(str_value.c_str());
			angle.push_back(d_value);
//			cout << " - angle="<<d_value;

			getline(iline, str_value, '\t');
			d_value = atof(str_value.c_str());
			major.push_back(d_value);
//			cout << " - major="<<d_value;

			getline(iline, str_value, '\t');
			d_value = atof(str_value.c_str());
			minor.push_back(d_value);
//			cout << " - minor="<<d_value << "\n";
		}

//		double tmp;
//		while(!input.eof())
//		{
//				input >> tmp; x_pos.push_back(tmp);
//				input >> tmp; y_pos.push_back(tmp);
//				input >> tmp; angle.push_back(tmp);
//				input >> tmp; major.push_back(tmp);
//				input >> tmp; minor.push_back(tmp);
//		}
		input.close();
	}
	else
	{
		cout << "ERROR: with file " << filename << " -> no such file or directory." << endl;
		exit(1);
	}

	vector<Shape*> ellipses;

	for(unsigned int i=0;i<x_pos.size();i++)
	{
		vector<double> pos (2,0);
		pos [0] = x_pos[i];
		pos [1] = y_pos[i];
		ellipses.push_back(new Ellipse(pos,flip_orientation(angle[i]),major[i]/2,minor[i]/2));
	}

	return ellipses;
}

double Ellipse::get_approximate_distance(vector<double> point){
	double delta_x = point[0]-center[0];
	double delta_y = point[1]-center[1];
	double pi = 3.14159265359;
	//0 <= Orientation angle <= pi, -pi/2 <= atan(x) <= pi/2
	double rel_angle = abs( orientation_angle - ( atan(delta_y/delta_x) + pi/2 ) );
	double eff_radius = sqrt(a*a*cos(rel_angle)*cos(rel_angle) + b*b*sin(rel_angle)*sin(rel_angle));
	return sqrt(delta_x*delta_x+delta_y*delta_y) - eff_radius;
}

double Ellipse::get_semi_major_axis(){
	return a;
}

double Ellipse::get_semi_minor_axis(){
	return b;
}

double Ellipse::get_orientation_angle(){
	return orientation_angle;
}

double Ellipse::flip_orientation(double angle)
{
	double pi = 3.14159265359;
	return abs(angle-pi);
}
